#coding=utf-8
#
# 版权所有 2011 沙发客团队
# 遵循Apache License 2.0协议
#    具体见 http://www.apache.org/licenses/LICENSE-2.0
#
'''

Created on 2011-3-16

@author: nava
'''

from weibopy.auth import OAuthHandler, BasicAuthHandler
from weibopy.api import API
from weibopy.error import WeibopError
from ConfigParser import ConfigParser
from const import *
from logger import Logger
from notification_manager import NotificationManager
import traceback, time, os, random, codecs, threading
#
# 全局函数
#
def StrToGbk(value):
    """ 支持中文，转成gb2312 """
    try:
        if isinstance(value, str):
            value    = unicode(value, "utf-8", errors="ignore")
    except:
        pass
    value    = value.encode('gb2312', "ignore")
    value    = value.decode('gb2312', "ignore")
    return value

def StrToUtf8(value):
    try:
        if isinstance(value, str):
            value = unicode(value, "utf-8")
    except:
        value = value.decode("gbk")

    return value

class WatchItem:
    def __init__(self, user_name = None):
        #
        # 监控的用户名
        #
        self.user_name          = user_name
        
        #
        # 注释计数器
        #
        self.comment_counter    = 0
        
        #
        # 转发计数器
        #
        self.retweet_counter    = 0
        
        #
        # 关注限制 
        #
        self.watch_level        = WATCH_LEVEL_ONCE
        
        
class WatchList:
    def __init__(self):
        #
        # 关注人员字典
        #
        self._watch_dict    = {}
        
        #
        # 配置处理文件
        #
        self._config_parser = None
        
        self._setting_parser = None
        
    def CheckUser(self, user_name, auto_add = False):
        """ 检查用户是否在监控列表中 """
        if user_name == None or len(user_name) <= 0:
            return None, False
        
        if self._watch_dict.has_key(user_name) == False:
            if auto_add == False:
                return None, False
            
            #
            # 如果自动添加，则生成添加列表
            #
            global DEFAULT_WATCH_LEVEL
            watch_item                  = WatchItem(user_name)
            watch_item.watch_level      = DEFAULT_WATCH_LEVEL
            self._watch_dict[user_name] = watch_item
            return watch_item, True
        
        watch_item = self._watch_dict[user_name]
        return watch_item, False
    
    def LoadSettingFromConfig(self):
        """ 从配置文件获取设置属性 """
        #
        # 检查配置文件
        #
        if self._setting_parser == None:
            self._setting_parser = ConfigParser()

        global USER_NAME, REQUEST_COUNT, IS_RECORD, COMMENT_ENABLE, RETWEET_ENABLE, \
               COMMENT_NUM, RETWEET_NUM, COMMENT_TEMPLATE_LIST, RETWEET_TEMPLATE_LIST

        try:
            self._setting_parser.readfp(codecs.open(CONFIG_SETTING_FILE, "r", "utf-8-sig"))
            #
            # 获取配置列表
            #
            section_list = self._setting_parser.sections()
            if len(section_list) < 4:
                raise

            for section_item in section_list:           
                #
                # 获取关键参数
                #
                if self._setting_parser.has_option(section_item, SETTING_USER_NAME):
                    USER_NAME = self._setting_parser.get(
                            section_item,
                            SETTING_USER_NAME)
                    USER_NAME = StrToUtf8(USER_NAME)
                    
                if self._setting_parser.has_option(section_item, SETTING_REQUEST_COUNT):
                    REQUEST_COUNT = self._setting_parser.getint(
                            section_item,
                            SETTING_REQUEST_COUNT)
    
                if self._setting_parser.has_option(section_item, SETTING_IS_RECORD):
                    IS_RECORD = self._setting_parser.getboolean(
                            section_item,
                            SETTING_IS_RECORD)
    
                if self._setting_parser.has_option(section_item, SETTING_COMMENT_ENABLE):
                    COMMENT_ENABLE = self._setting_parser.getint(
                            section_item,
                            SETTING_COMMENT_ENABLE)
    
                if self._setting_parser.has_option(section_item, SETTING_RETWEET_ENABLE):
                    RETWEET_ENABLE = self._setting_parser.getint(
                            section_item,
                            SETTING_RETWEET_ENABLE)
    
                if self._setting_parser.has_option(section_item, SETTING_COMMENT_NUM):
                    COMMENT_NUM = self._setting_parser.getint(
                            section_item,
                            SETTING_COMMENT_NUM)
    
                if self._setting_parser.has_option(section_item, SETTING_RETWEET_NUM):
                    RETWEET_NUM = self._setting_parser.getint(
                            section_item,
                            SETTING_RETWEET_NUM)

                if self._setting_parser.has_option(section_item, SETTING_WATCH_LEVEL):
                    DEFAULT_WATCH_LEVEL = self._setting_parser.getint(
                            section_item,
                            SETTING_WATCH_LEVEL)
    
                section_name = StrToUtf8(section_item)
                if section_name == SECTION_NAME_COMMENT or section_name == SECTION_NAME_RETWEET:
                    section_option_list = self._setting_parser.options(section_item)
                    for section_option in section_option_list:
                        template = StrToUtf8(section_option)
                        if section_name == SECTION_NAME_COMMENT:
                            COMMENT_TEMPLATE_LIST.append(template)
                        else:  
                            RETWEET_TEMPLATE_LIST.append(template)
        except:
            #
            # 设置文件已经出现异常
            #
            self.RestoreSettingToConfig()

        return True

    def LoadFromConfig(self):
        """ 从配置文件中获取关注列表 """
        #
        # 检查配置文件
        #
        if os.path.exists(CONFIG_FILE) == False:
            return False
        
        if self._config_parser == None:
            self._config_parser = ConfigParser()

        self._config_parser.readfp(codecs.open(CONFIG_FILE, "r", "utf-8-sig"))

        #
        # 获取配置列表
        #
        section_list = self._config_parser.sections()
        for section_item in section_list:
            watch_item              = WatchItem()
            watch_item.watch_level  = DEFAULT_WATCH_LEVEL
            #
            # 用户名需要转换成unicode
            #
            watch_item.user_name = section_item
            #
            # 获取关键参数
            #
            if self._config_parser.has_option(section_item, CONFIG_COMMENT_COUNTER):
                watch_item.comment_counter = self._config_parser.getint(
                        section_item,
                        CONFIG_COMMENT_COUNTER)
            if self._config_parser.has_option(section_item, CONFIG_RETWEET_COUNTER):
                watch_item.retweet_counter = self._config_parser.getint(
                        section_item,
                        CONFIG_RETWEET_COUNTER)
            if self._config_parser.has_option(section_item, CONFIG_WATCH_LEVEL):
                watch_item.watch_level = self._config_parser.getint(
                        section_item,
                        CONFIG_WATCH_LEVEL)
            
            #
            # 未做唯一性检查，可能会覆盖相同名字的section
            #
            self._watch_dict[watch_item.user_name] = watch_item

        return True
    
    def SaveToConfig(self):
        """ 将关注列表信息保存到配置文件中 """
        if self._config_parser == None:
            self._config_parser = ConfigParser()
            #
            # 存在老的配置文件
            #
            if os.path.exists(CONFIG_FILE):
                self._config_parser.readfp(codecs.open(CONFIG_FILE, "r", "utf-8-sig"))

        for section, watch_item  in self._watch_dict.items():
            #section = str(section)
            if self._config_parser.has_section(section) == False:
                self._config_parser.add_section(section)

            self._config_parser.set(section, 
                CONFIG_COMMENT_COUNTER, 
                watch_item.comment_counter)
            self._config_parser.set(section, 
                CONFIG_RETWEET_COUNTER, 
                watch_item.retweet_counter)
            self._config_parser.set(section, 
                CONFIG_WATCH_LEVEL, 
                watch_item.watch_level)

        try:
            #self._config_parser.readfp(codecs.open(CONFIG_FILE, "r", "utf-8-sig"))
            #f = codecs.open(CONFIG_FILE, "w", "utf-8-sig")
            f = open(CONFIG_FILE, "w")
            self._config_parser.write(f)
            f.close()
        except Exception, ex:
            print ex
            return False

        return True
    
    def RestoreSettingToConfig(self):
        """ 如果读取配置文件失败,重新生成默认配置 """
        #
        # TODO 调用此函数需要提示用户重新输入用户名和密码
        #
        if os.path.exists(CONFIG_SETTING_FILE):
            f = open(CONFIG_SETTING_FILE, 'w')
            f.close()

        self._setting_parser = ConfigParser()
        
        if self._setting_parser.has_section(SECTION_NAME_ACCOUNT) == False:
            self._setting_parser.add_section(SECTION_NAME_ACCOUNT)

        self._setting_parser.set(SECTION_NAME_ACCOUNT,
            SETTING_USER_NAME,
            USER_NAME)

        if self._setting_parser.has_section(SECTION_NAME_SHAFA) == False:
            self._setting_parser.add_section(SECTION_NAME_SHAFA)

        self._setting_parser.set(SECTION_NAME_SHAFA,
            SETTING_REQUEST_COUNT, 
            REQUEST_COUNT)
        self._setting_parser.set(SECTION_NAME_SHAFA,
            SETTING_IS_RECORD, 
            IS_RECORD)
        self._setting_parser.set(SECTION_NAME_SHAFA,
            SETTING_COMMENT_NUM, 
            COMMENT_NUM)
        self._setting_parser.set(SECTION_NAME_SHAFA,
            SETTING_RETWEET_NUM, 
            RETWEET_NUM)
        self._setting_parser.set(SECTION_NAME_SHAFA,
            SETTING_COMMENT_ENABLE, 
            COMMENT_ENABLE)
        self._setting_parser.set(SECTION_NAME_SHAFA,
            SETTING_RETWEET_ENABLE, 
            RETWEET_ENABLE)
        self._setting_parser.set(SECTION_NAME_SHAFA,
            SETTING_WATCH_LEVEL, 
            DEFAULT_WATCH_LEVEL)

        if self._setting_parser.has_section(SECTION_NAME_COMMENT) == False:
            self._setting_parser.add_section(SECTION_NAME_COMMENT)

        self._setting_parser.set(SECTION_NAME_COMMENT,
            DEFAULT_COMMENT_TEMPLATE, 
            1)
        
        if self._setting_parser.has_section(SECTION_NAME_RETWEET) == False:
            self._setting_parser.add_section(SECTION_NAME_RETWEET)

        self._setting_parser.set(SECTION_NAME_RETWEET,
            DEFAULT_RETWEET_TEMPLATE, 
            1)

        try:
            f = open(CONFIG_SETTING_FILE, "w")
            self._setting_parser.write(f)
            f.close()
        except Exception, ex:
            print ex
            return False

        return True


class Shafa(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self, name = "core thread")
        self._thread_manager = ThreadManager()
        self.is_continue = True
        #
        # 用户自己的名称
        #
        self._displayname   = None
        
        #
        # sf 数量
        #
        self._sf_sum = 0
        
        #
        # sf 数量
        #
        self._report_sum = 0
        
        #
        # 微博上线
        #
        self._weiboHalt = False
        
        #
        # 回复上线
        #
        self._commentHalt = False
        
        #
        # 恢复时间
        #
        self._weiboTime    = 0
        
        #
        # 已经发送字典列表
        #
        self._tweet_dict    = {}
        
        #
        # 成功发表评论的字典,通过获取评论信息判断是否抢到了沙发
        #
        self._success_comment_dict = {}
        
        #
        # TODO: 从配置文件中获取
        #
        self._watch_list    = WatchList()
        self._logger        = Logger()
        self._notification_manager = NotificationManager()
        self._last_comment  = u""
        self._last_retweet  = u""
    
    def StrToGbk(self, value):
        """ 让托盘支持中文，转成gb2312 """
        try:
            if isinstance(value, str):
                value    = unicode(value, "utf-8", errors="ignore")
        except:
            pass
        value    = value.encode('gb2312', "ignore")
        value    = value.decode('gb2312', "ignore")
        return value
    
    def __GetWeiboCount(self, id):
        """ 获取微博评论和转发条数 """
        if self._api == None:
            return -1, -1
        comment_count   = 0
        rt_count        = 0
        try:
            shafa_counts = self._api.counts(ids = id)
            if shafa_counts == None or len(shafa_counts) <= 0:
                self._logger.info("__GetWeiboCount 获取count失败")
                return -1, -1
            
            #
            # 获取计数器
            #
            shafa_count      = shafa_counts[0]
            comment_count    = shafa_count.comments
            rt_count         = shafa_count.rt
            
        except Exception:
            self._logger.info("__GetWeiboCount出现异常 获取count失败")
            return -1, -1
        return comment_count, rt_count

    def Retweet(self, shafa_item):
        """ 推送消息 """
        if shafa_item == None:
            return False

        if self._commentHalt:
            self._logger.info(u"re com全上线了，休息休息 ")
            return False
            
        need_to_save = False
        
        
        try:
            if self._api == None:
                self._api = API(self._auth,
                        host    = WEIBO_HOST, 
                        source  = APP_KEY)
                
            comment_count, rt_count = self.__GetWeiboCount(shafa_item.id)
            if comment_count == -1 or rt_count == -1:
                return False
           
            #
            # 获取作者名字
            #
            author       = shafa_item.author.name
            #
            # 屏蔽自己发的帖子
            #
            if self._displayname == author:
                return False
            
            #
            # 不处理包含自己名称的转发
            #
            if shafa_item.text.find("@%s" % self._displayname) >= 0:
                return False
            
            #
            # 用户不在则可以自动添加
            #
            watch_item, need_to_save = self._watch_list.CheckUser(author, IS_RECORD)
            if watch_item == None:
                return False

            #
            # 为0表面不进行监控
            #
            if watch_item.watch_level == 0:
                return False

            text = shafa_item.text[0:10]
            self._logger.info(u"作者:%s 内容:%s...  转发数量:%d 评论数量:%d" %(
                author,
                text,
                rt_count,
                comment_count))

            #
            # 准备
            #
            self._thread_manager.AnotherRush()

            #
            # weiboid
            #
            id = 0
            #
            # 只坐沙发评论，后面可以考虑开放需求
            #
            if self._commentHalt == False and COMMENT_ENABLE and \
                comment_count == COMMENT_NUM:
                message = self.GetCommentText(author, watch_item.comment_counter + 1)
                
                #
                # id + type为关键字，避免重复发帖
                #
                key = "%d1" % (shafa_item.id)
                if self._tweet_dict.has_key(key) == False:
                   
                    message = self.StrToGbk(message)
                    #
                    # 先加入字典，出现异常后不再继续处理
                    #
                    self._tweet_dict[key] = 1
                    
                    #
                    # 通知UI有沙发需要抢
                    #
                    self._notification_manager.UpdateRushTime(
                        u"抢%s的沙发？ 内容:%s..." % (author, text[0:7]),
                        TIME_MAX_RUSH_WAIT
                        )
                    
                    self._thread_manager.WaitRush(TIME_MAX_RUSH_WAIT + 0.1)
                    if self._thread_manager.ReadyToRush():
                        self._success_comment_dict[shafa_item] = message
                        
                        self._api.reply(shafa_item.id, 
                                       shafa_item.mid, 
                                       message)
                        
                        self._thread_manager.user_rushed = True
                        need_to_save = True
                        if watch_item.watch_level == WATCH_LEVEL_ONCE:
                            watch_item.watch_level = WATCH_LEVEL_NONE
            #
            # 转发处理列表
            #
            if RETWEET_ENABLE and rt_count == RETWEET_NUM and \
                self._weiboHalt == False:
                
                #
                # 未评论或评论失败
                #
                if id == 0:
                    message = ""
                else:
                    mid = self._api.querymid(id, 1)
                    url = "http://t.sina.com.cn/%d/%s" % (id, mid.mid)
                    message = self.GetRetweetText(author, watch_item.comment_counter, url)

                key = "%d2" % (shafa_item.id)
                
                if self._tweet_dict.has_key(key) == False:
                    message = self.StrToGbk(message)
 
                    #
                    # 先加入字典，出现异常后不再继续处理
                    #
                    self._tweet_dict[key] = 1
                    
                    #
                    # 如果已经提示用户，者不再重新提醒
                    #
                    if self._thread_manager.ReadyToRush() == False:
                        #
                        # 通知UI有沙发需要抢
                        #
                        self._notification_manager.UpdateRushTime(
                            u"转发%s的微博？ 内容:%s..." % (author, text[0:7]),
                            TIME_MAX_RUSH_WAIT
                            )
                        self._thread_manager.WaitRush(TIME_MAX_RUSH_WAIT + 0.1)

                    if self._thread_manager.ReadyToRush():
                        _ = self._api.repost(shafa_item.id, 
                                        message)
                        
                        self._thread_manager.user_rushed = True
                        _, r_count = self.__GetWeiboCount(id)
    
                        #
                        # 修改登录逻辑 
                        #
                        need_to_save = True
                        if watch_item.watch_level == WATCH_LEVEL_ONCE:
                            watch_item.watch_level = WATCH_LEVEL_NONE
                        #
                        # 检查是否抢到沙发
                        #
                        if r_count <= rt_count + 1:
                            watch_item.retweet_counter += 1
                            self._report_sum += 1
        except WeibopError, e:
            
            #
            # TODO: 处理服务器返回的错误逻辑
            #
 
            if str(e).startswith(u"error_code:400,40028"):
                self._logger.info(u"sina让我们休息了, 休息十分钟")
                #
                # 通知ui
                #
                self._notification_manager.UpdateShafaSleepTime(u"sina让我们休息了, 休息十分钟", TIME_SLEEP_TIME)
                self._thread_manager.wait(TIME_SLEEP_TIME)
                self._api = None
                return False

            #
            # 回复
            #
            if str(e) == u"error_code:403,40305:Error: update comment out of rate limit!":
                self._logger.info(u"评论上限, time : %d " % time.time())
                self._commentHalt = True
                return False
            #
            # 微博
            #
            if str(e) == u"error_code:403,40308:Error: Update weibo out of rate limit!":
                self._weiboTime = time.time()
                self._logger.info(u"weibo 发送上限, time : %d " % self._weiboTime)
                self._weiboHalt = True
                return False
            
            self._logger.warning(e)
            
        finally:
            if need_to_save == True:
                self._watch_list.SaveToConfig()
                
            if self._thread_manager.ReadyToRush() and \
                self._thread_manager.UserRushed() == False:
                self._notification_manager.UpdateShafaMessage(u"没抢上沙发")
       
        return True
    
    def __AdjustSleepTime(self, rate_limit):
        """ 获取请求之间的间隔事件 """
        sleep_time  = INTERVAL_TIME_MIN
        if rate_limit == None:
            return sleep_time
        #
        # 计算每次调用请求的间隔时间
        #
        if rate_limit.remaining_hits > 0:
            sleep_time  = rate_limit.reset_time_in_seconds / rate_limit.remaining_hits
        
        #
        # 调整间隔时间
        #
        if sleep_time < INTERVAL_TIME_MIN:
            sleep_time = INTERVAL_TIME_MIN
        elif sleep_time > INTERVAL_TIME_MAX:
            sleep_time = INTERVAL_TIME_MAX

        return sleep_time

    def LoginAuthHandler(self):
        """登陆验证"""
        try:
            self._auth = OAuthHandler(APP_KEY, APP_SECRET)
            #
            # 获取用户授权验证地址并打开浏览器
            #
            auth_url = self._auth.get_authorization_url()
            import win32api, win32con
            win32api.ShellExecute(0, 'open', auth_url, '','',win32con.SW_NORMAL)

            verifier = raw_input('PIN: ').strip()
            self._auth.get_access_token(verifier)
            self._api = API(self._auth)
        except Exception, ex:
            #
            # 登陆异常处理
            #
            print ex
            pass
    
    def StopThread(self):
        """关闭线程资源"""
        self.is_continue = False
    
    def run(self):
        rate_limit = None

        try:
            #
            # 从配置文件中获取监控信息
            #
            self._watch_list.LoadSettingFromConfig()
            self._watch_list.LoadFromConfig()
            #
            # 完成最基本的登录验证
            #
            self._auth = BasicAuthHandler(self._thread_manager.user_name, self._thread_manager.password)
            self._api = API(self._auth,
                            host    = WEIBO_HOST, 
                            source  = APP_KEY)
            #self.LoginAuthHandler()
            
            #
            # 获取用户自己的信息
            #
            user = self._api.verify_credentials()
            if user:
                self._displayname = user.screen_name
            else:
                self._displayname = self._thread_manager.user_name

        except Exception, ex:
            print ex
            print traceback.format_exc()

        #
        # 记录请求的最大微博id
        #
        max_id      = 0
        count       = 1
        sleep_time  = INTERVAL_TIME_MIN

        #
        # 通知ui
        #
        self._notification_manager.UpdateShafaMessage(u"开始抢沙发了")
 
        while self.is_continue:
            try:
                if self._api == None:
                    self._api = API(self._auth,
                        host    = WEIBO_HOST, 
                        source  = APP_KEY)
                #
                # 用以决定用户的逻辑操作
                #
                rate_limit = self._api.rate_limit_status()
                if rate_limit.remaining_hits <= 10:
                    self._thread_manager.wait(2)
                    continue
                
                #
                # 获取请求之间的间隔时间
                #
                sleep_time  = self.__AdjustSleepTime(rate_limit)
                if (count % 20) == 0:
                    self._logger.info(u"限制次数:%d 剩余次数:%d 间隔时间:%d 请求次数:%d" % (
                        rate_limit.hourly_limit,
                        rate_limit.remaining_hits,
                        sleep_time,
                        count))
                #
                # 获取所有朋友的列表，加入since_id可以避免重复请求数据
                #
                timeline = self._api.friends_timeline(
                    count    = REQUEST_COUNT, 
                    page     = 1, 
                    since_id = max_id
                    )
                
                for shafa_item in timeline:
                    
                    self.Retweet(shafa_item)
                    
                    if max_id < shafa_item.id:
                        max_id = shafa_item.id
                        
                    #
                    # 间隔1秒发送一次请求
                    #
                    if self._commentHalt:
                        self._logger.info(u"评论上限，休息十分钟")
                        #
                        # 通知ui
                        #
                        self._notification_manager.UpdateShafaCount(self._sf_sum,
                                                            self._report_sum )
                        self._notification_manager.UpdateShafaSleepTime(u"评论上限，休息十分钟", TIME_COMMENT_HALT)
                        self._thread_manager.wait(TIME_COMMENT_HALT)
                        self._commentHalt   = False
                        self._weiboHalt     = False
                        
                    self._logger.info(u"你 已经 评论%d 条, 转发 %d 条" % (
                                        self._sf_sum,
                                        self._report_sum ))
                    
                    self._notification_manager.UpdateShafaCount(self._sf_sum,
                                                                self._report_sum )
                    #
                    # 间隔1秒发送一次请求
                    #
                    self._thread_manager.wait(TIME_INTERVAL_MESSAGE)

                #
                # 确认是否成功抢到沙发,更新统计信息
                #
                for shafa_item, comment_text in self._success_comment_dict.items():
                    author = shafa_item.author.name
                    comments = self._api.comments(
                        id = shafa_item.id
                        )
                    if len(comments) <= 0 or comments[-1].text == comment_text:
                        #
                        # 成功抢到沙发,更新计数器
                        #
                        
                        self._sf_sum += 1
                        watch_item, _ = self._watch_list.CheckUser(author, IS_RECORD)
                        if watch_item:
                            watch_item.comment_counter += 1

                        self._logger.info("沙发内容:%s" % comment_text)

                        self._notification_manager.UpdateShafaMessage(u"作者:%s 内容:%s \n沙发内容:%s" %(author, shafa_item.text[0:10], comment_text))
                    else:
                        #
                        # 通知UI
                        #
                        fail_text = "抢%s的沙发失败" % author
                        self._logger.info(fail_text)
                        self._notification_manager.UpdateShafaMessage(fail_text)

                self._success_comment_dict.clear()
                #
                # 休息一小时
                #
                if self._weiboHalt:
                    if (time.time() - self._weiboTime) < 3600:
                        self._weiboHalt = False
 
                self._thread_manager.wait(sleep_time)
                count += 1

            except Exception, ex:
                
                self._logger.warning(ex)
                self._logger.warning(traceback.format_exc())
                
                #
                # 赋值为空，重新建立连接
                #
                self._api = None
                
            finally:
                pass
            if self.is_continue == False:
                break

        #
        # 退出循环后需要保存到配置文件中
        #
        self._watch_list.SaveToConfig()

    def GetCommentText(self, name, number):
        try:
            template_len = len(COMMENT_TEMPLATE_LIST)
            if template_len > 0:
                if template_len == 1:
                    text = COMMENT_TEMPLATE_LIST[0]
                else:
                    text = COMMENT_TEMPLATE_LIST[random.randint(0, template_len - 1)]
                    while text == self._last_comment:
                        text = COMMENT_TEMPLATE_LIST[random.randint(0, template_len - 1)]

                self._last_comment = text

                if text.find(u"*作者*") >= 0:
                    text = text.replace(u"*作者*", name)

                if text.find(u"*次数*") >= 0:
                    text = text.replace(u"*次数*", str(number))
            else:
                raise
        except:
            text = DEFAULT_COMMENT_TEMPLATE.replace(u"*作者*", name)
            text = text.replace(u"*次数*", str(number))

        return text
    
    def GetRetweetText(self, name, number, address):
        try:
            template_len = len(RETWEET_TEMPLATE_LIST)
            if template_len > 0:
                if template_len == 1:
                    text = RETWEET_TEMPLATE_LIST[0]
                else:
                    text = RETWEET_TEMPLATE_LIST[random.randint(0, template_len - 1)] 
                    while text == self._last_retweet:
                        text = RETWEET_TEMPLATE_LIST[random.randint(0, template_len - 1)]

                self._last_retweet = text

                if text.find(u"*作者*") >= 0:
                    text = text.replace(u"*作者*", name)
                    
                if text.find(u"*次数*") >= 0:
                    text = text.replace(u"*次数*", str(number))
                    
                if text.find(u"*地址*") >= 0:
                    text = text.replace(u"*地址*", str(address))
            else:
                raise
        except:
            text = DEFAULT_RETWEET_TEMPLATE % (name, number)

        return text

class ThreadManager:
    """ EBox的核心处理模块 """

    # =============================================
    # 唯一实例开始位置
    # =============================================
    class __impl:
        """ Implementation of the singleton interface """

    # storage for the instance reference
    __instance = None
    
    def __getattr__(self, attr):
        """ Delegate access to implementation """
        return getattr(self.__instance, attr)

    def __setattr__(self, attr, value):
        """ Delegate access to implementation """
        return setattr(self.__instance, attr, value)
    # =============================================
    # 唯一实例结束位置
    # =============================================
    

    def __init__(self):
        """ Create singleton instance """   
        # Check whether we already have an instance
        if ThreadManager.__instance is None:
            # Create and remember instance
            ThreadManager.__instance             = ThreadManager.__impl()
            
            self._init                  = False
            self._shafake_thread        = None
            self.stop_thread_event      = threading.Event()
            
            #
            # 是否抢沙发的关键性事件
            #
            self.rush_thread_event      = threading.Event()
            #
            # 用户选择了是否抢沙发
            #
            self.user_rushed            = False

            # 用户名
            self.user_name              = u""
            self.password               = u""
            self.main_panel             = None
            
    def StartShafa(self):
        """ 启动EBox核心服务 """
        #
        # 检测是否启动了本地线程，如果已经启动，则不做任何处理
        #
        if (self._init == True):
            return True
        #
        # 启动核心线程
        #
        self._shafake_thread = Shafa()
        self._shafake_thread.start()
        #
        # 表明已经完成初始化启动
        #
        #
        # Step3, 启动本地监控模块
        #
        self._init = True
        return True
    
    def wait(self, time):
        """ 等待制定的时间 """
        return self.stop_thread_event.wait(time)

    def StopShafa(self):
        """ 关闭沙发客程序 """
        if self._init == False:
            return
        
        self._shafake_thread.StopThread()
        self.stop_thread_event.set()
        time.sleep(0.1)
        
    def WaitRush(self, time):
        """ 等待抢沙发的时间 """
        return self.rush_thread_event.wait(time)
    
    def ReadyToRush(self):
        """ 判断是否抢沙发 """
        return self.rush_thread_event.isSet()

    def YouMustRush(self):
        """ 发送抢沙发指令 """
        return self.rush_thread_event.set()
    
    def UserRushed(self):
        """ 用户是否发送了抢沙发的指令 """
        return self.user_rushed
    
    def AnotherRush(self):
        """ 准备另外一个抢沙发事件 """
        if self.rush_thread_event.isSet():
            self.rush_thread_event.clear()
            
        self.user_rushed = False
#
# 程序主入口地址
#
if __name__ == '__main__':
    shafake = Shafa()
    shafake.run()